#include "spi_flash_op.h"
#include "print_rtt.h"
#include "string.h"
#define SPI_TEST 0
#if SPI_TEST
uint8_t write_data[1024];
uint8_t read_data[1024];
void SoftSPIFlash_test(void)
{
  int ret;
  SoftSPIFlash_Read(0x000000, read_data, 1024);
  SoftSPIFlash_SectorErase(0x000000);
  if (ret != 0)
  {
    while (1)
      ;
  }
  SoftSPIFlash_Read(0x000000, read_data, 1024);

  for (int i = 0; i < 1024; i++)
  {
    write_data[i] = i;
  }
  SoftSPIFlash_PageWrite(0x000000, write_data, 256);

  if (ret != 0)
  {
    while (1)
      ;
  }
  SoftSPIFlash_Read(0x000000, read_data, 1024);

  SoftSPIFlash_PageWrite(0x000100, &write_data[256], 256);

  SoftSPIFlash_Read(0x000000, &read_data[0], 1024);
  ;
  SoftSPIFlash_PageWrite(0x000200, &write_data[512], 256);
  SoftSPIFlash_Read(0x000000, &read_data[0], 1024);

  SoftSPIFlash_PageWrite(0x000300, &write_data[768], 256);

  SoftSPIFlash_Read(0x000000, &read_data[0], 1024);

  ret = memcmp(read_data, write_data, 1024);
  if (ret != 0)
  {
    while (1)
      ;
  }
  SoftSPIFlash_SectorErase(0x000000);
  if (ret != 0)
  {
    while (1)
      ;
  }
}
#endif
/* ---------- 初始化 ---------- */
void SoftSPIFlash_Init(void)
{
  RCC_AHB1ENR |= 1 << 4; // 使能 GPIOE 时钟
  /* PE2/3/5 输出，PE4 输入 */
  GPIOE_MODER &= ~(0x3F << 4);                    // 清掉 PE2/PE3/PE4/PE5
  GPIOE_MODER |= (1 << 4) | (1 << 6) | (1 << 10); // PE2/PE3/PE5 = OUT
  // PE4 默认就是输入
  SoftSPI_FLASH_CS_H();
  SoftSPI_FLASH_SCK_L();
}

/* ---------- 收发 1 Byte ---------- */
uint8_t SoftSPIFlash_RW(uint8_t out)
{
  uint8_t in = 0;
  for (uint8_t i = 0; i < 8; i++)
  {
    /* 输出 bit7-i */
    if (out & 0x80)
      SoftSPI_FLASH_MOSI_H();
    else
      SoftSPI_FLASH_MOSI_L();
    out <<= 1;

    SoftSPI_FLASH_SCK_H(); // 上升沿采样
    in <<= 1;
    if (SoftSPI_FLASH_MISO)
      in |= 1;
    SoftSPI_FLASH_SCK_L(); // 下降沿准备
  }
  return in;
}

/* ---------- 读 Flash ID 示例 ---------- */
uint32_t SoftSPIFlash_ReadJEDEC(void)
{
  uint32_t id;
  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(0x9F); // JEDEC ID 命令
  id = SoftSPIFlash_RW(0xFF) << 16;
  id |= SoftSPIFlash_RW(0xFF) << 8;
  id |= SoftSPIFlash_RW(0xFF);
  SoftSPI_FLASH_CS_H();
  return id;
}
static int SoftSPIFlash_WaitBusy(void)
{
  uint8_t sr;
  int times = 0;
  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(CMD_READ_STATUS);
  do
  {
    sr = SoftSPIFlash_RW(0);
    times++;
    if (times > 0x000FFFFF)
    {
      SoftSPI_FLASH_CS_H();
      return -1;
    }
  } while (sr & 0x01);
  SoftSPI_FLASH_CS_H();
  return 0;
}
uint32_t SoftSPIFlash_ReadID(void)
{
  uint32_t id = 0;
  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(CMD_JEDEC_ID);
  id = SoftSPIFlash_RW(0) << 16; // 0xEF
  id |= SoftSPIFlash_RW(0) << 8; // 0x40
  id |= SoftSPIFlash_RW(0);      // 0x15
  SoftSPI_FLASH_CS_H();
  return id; // 返回 0xEF4015
}
void SoftSPIFlash_PageWrite(uint32_t addr, const uint8_t *buf, uint16_t len)
{
  SoftSPIFlash_WaitBusy();
  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(CMD_WRITE_ENABLE);
  SoftSPI_FLASH_CS_H();

  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(CMD_PAGE_PROGRAM);
  SoftSPIFlash_RW(addr >> 16);
  SoftSPIFlash_RW(addr >> 8);
  SoftSPIFlash_RW(addr);
  while (len--)
    SoftSPIFlash_RW(*buf++);
  SoftSPI_FLASH_CS_H();
  SoftSPIFlash_WaitBusy();
}
void SoftSPIFlash_Read(uint32_t addr, uint8_t *buf, uint32_t len)
{
  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(CMD_READ_DATA);
  SoftSPIFlash_RW(addr >> 16);
  SoftSPIFlash_RW(addr >> 8);
  SoftSPIFlash_RW(addr);
  while (len--)
    *buf++ = SoftSPIFlash_RW(0);
  SoftSPI_FLASH_CS_H();
}

void SoftSPIFlash_SectorErase(uint32_t addr) // addr 必须 4 KB 对齐 (0x1000)
{
  SoftSPIFlash_WaitBusy(); // 1. 等待空闲

  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(CMD_WRITE_ENABLE); // 2. 写使能
  SoftSPI_FLASH_CS_H();

  SoftSPI_FLASH_CS_L();
  SoftSPIFlash_RW(CMD_SECTOR_ERASE); // 3. 发指令 + 3 字节地址
  SoftSPIFlash_RW(addr >> 16);
  SoftSPIFlash_RW(addr >> 8);
  SoftSPIFlash_RW(addr);
  SoftSPI_FLASH_CS_H();

  SoftSPIFlash_WaitBusy(); // 4. 等待擦完（典型 60 ms）
}
#define OTA_SIZE_KB    768
#define OTA_START_ADDR 0x000000
#define SECTOR_SIZE    4096
#define SECTOR_NUM     192       /* 192 */
static uint8_t buf[SECTOR_SIZE]; /* 临时读缓存 */
int OTA_Flash_EraseAndVerify(void)
{
  uint32_t addr;
  int fail = 0;

  // printf(">>> Start erase %d KB (%d Sectors) ...\r\n", OTA_SIZE_KB, SECTOR_NUM);

  for (uint16_t i = 0; i < SECTOR_NUM; i++)
  {
    addr = OTA_START_ADDR + i * SECTOR_SIZE;

    /* 1. 擦除 */
    SoftSPIFlash_SectorErase(addr); // 你的底层擦除函数
                                    //    while (SoftSPIFlash_Bus())
    ;                               // 等待 BUSY 位归零

    /* 2. 回读整 Sector */
    SoftSPIFlash_Read(addr, buf, SECTOR_SIZE); // 底层读函数

    /* 3. 校验是否全 0xFF */
    for (int j = 0; j < SECTOR_SIZE; j++)
    {
      if (buf[j] != 0xFF)
      {
        LOG_ERROR("Erase verify fail @ Sector %d, addr 0x%06lX, byte %d = 0x%02X\r\n",
                  i, addr + j, j, buf[j]);
        fail++;
        goto end;
      }
    }

    /* 可选进度条 */
    if ((i & 0xF) == 0)
      LOG_INFO("  erased %d/%d sectors\r\n", i, SECTOR_NUM);
  }

end:
  if (!fail)
    LOG_INFO(">>> %d KB erase & verify PASSED\r\n", OTA_SIZE_KB);
  else
    LOG_ERROR(">>> %d KB erase & verify FAILED (%d errors)\r\n", OTA_SIZE_KB, fail);

  return fail;
}
int SPIFlash_Write1K_InBound(uint32_t addr,
                             const uint8_t *src,
                             uint8_t *wrote_data,
                             uint16_t len)
{
  if (len == 0 || len > 1024)
    return -2;
  if ((addr & 0xFF) + len > 1024)
    return -2; /* 跨页保护 */

  uint32_t cur = addr;
  uint16_t left = len;

  /* 1. 按页写入（每页最多 256 B）*/
  while (left > 0)
  {
    uint16_t chunk = (left > 256) ? 256 : left;
    SoftSPIFlash_PageWrite(cur, src, chunk);
    // while (SoftSPIFlash_Bus())
    //   ;
    cur += chunk;
    src += chunk;
    left -= chunk;
  }

  /* 2. 一次性读回 */
  SoftSPIFlash_Read(addr, wrote_data, len);

  /* 3. 校验 */
  return (memcmp(src - len, wrote_data, len) == 0) ? 0 : -1;
}


